package com.minelx.scriptbuilder.parse.parser;

import com.minelx.scriptbuilder.script.attribute.clazz.Class;
import com.minelx.sequence.*;
import com.minelx.scriptbuilder.script.ScriptContext;
import com.minelx.scriptbuilder.script.attribute.function.MethodFactory;
import com.minelx.scriptbuilder.script.attribute.value.IAttribute;
import com.minelx.scriptbuilder.script.operation.ClassDeclareOperation;
import com.minelx.scriptbuilder.script.operation.CompositeOperation;
import com.minelx.scriptbuilder.script.operation.IOperation;

import static com.minelx.sequence.Collector.toList;

public class ClassesParser implements ReturnMatcher<IOperation, IStringScanner> {

	private final ScriptContext context;

	private final IAttribute declareOn;

	public ClassesParser(ScriptContext context, IAttribute declareOn) {
		this.context = context;
		this.declareOn = declareOn;
	}

	@Override
	public IOperation onMatched(IStringScanner scanner) {
		scanner.pass("class");
		scanner.trim();
		String className = scanner.nextPage();
		scanner.nextChar(); // '{'
		Class aClass = new Class();
		CompositeOperation functionDeclarations = new CompositeOperation();
		functionDeclarations.addAll(
				scanner.sequence(new FunctionDeclareOperationsParser(context, aClass, new MethodFactory()))
						.collect(toList())
		);
		scanner.nextChar(); // '}'
		return new ClassDeclareOperation(declareOn, className, aClass, functionDeclarations);
	}

	@Override
	public boolean isMatch(IStringScanner scanner) {
		return scanner.exists("class");
	}

	public static void eval(ScriptContext context, IAttribute declareOn, String source) {
		new ClassesParser(context, declareOn).get(new TrimmedStringScanner(new StringScanner(source))).execute();
	}
}
